home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / vroom / multicast.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  7.1 KB  |  266 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /***************************************************************************
  18.  *
  19.  * @(#) - Oort - Multicast Socket Routines.
  20.  *
  21.  * $Id: multicast.c,v 1.2 1994/01/02 07:27:39 fouts Exp $
  22.  *
  23.  *                    Chris Fouts - Silicon Graphics, Inc.
  24.  *                    October, 1991
  25.  **************************************************************************/
  26. /*                                                              */
  27. /*      Copyright (c) 1991-1993 SGI   All Rights Reserved       */
  28. /*      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI      */
  29. /*      The copyright notice above does not evidence any        */
  30. /*      actual or intended publication of such source code,     */
  31. /*      and is an unpublished work by Silicon Graphics, Inc.    */
  32. /*      This material contains CONFIDENTIAL INFORMATION that    */
  33. /*      is the property of Silicon Graphics, Inc. Any use,      */
  34. /*      duplication or disclosure not specifically authorized   */
  35. /*      by Silicon Graphics is strictly prohibited.             */
  36. /*                                                              */
  37. /*      RESTRICTED RIGHTS LEGEND:                               */
  38. /*      Use, duplication or disclosure by the                   */
  39. /*      Government is subject to restrictions                   */
  40. /*      as set forth in subdivision (c)(1)(ii) of               */
  41. /*      the Rights in Technical Data and Computer               */
  42. /*      Software clause at DFARS 52.227-7013,                   */
  43. /*      and/or in similar or successor clauses in the FAR,      */
  44. /*      DOD or NASA FAR Supplement. Unpublished- rights         */
  45. /*      reserved under the Copyright Laws of the United States. */
  46. /*      Contractor is SILICON GRAPHICS, INC., 2011 N. Shoreline */
  47. /*      Blvd., Mountain View, CA 94039-7311                     */
  48. /*                                                              */
  49. #include <stdlib.h>
  50. #include <bstring.h>
  51. #include <getopt.h>
  52. #include <string.h>
  53. #include <stdio.h>
  54. #include <time.h>
  55. #include <ctype.h>
  56. #include <unistd.h>
  57. #include <sys/types.h>
  58. #include <sys/socket.h>
  59. #include <net/if.h>
  60. #include <netinet/in.h>
  61. #include <net/soioctl.h>
  62. #include <arpa/inet.h>
  63. #include <fcntl.h>
  64. #include "multicast.h"
  65.  
  66.  
  67. int ioctl( int fildes, int request, ... ) ;
  68.  
  69. /* BEGIN PROTOTYPES -S multicast.c */
  70. static int  checkInterface( const char *interface, int fd, char mode,
  71.                 struct in_addr *ifaddr ) ;
  72. /* END PROTOTYPES -S multicast.c */
  73.  
  74.  
  75. /*------------------------------------------------------------------------------
  76.  * Open up a multicast socket for reading or writing.
  77.  *----------------------------------------------------------------------------*/
  78. int
  79. openMulticastSocket(
  80.     struct sockaddr_in    *addr,
  81.     u_short            port,
  82.     u_char            ttl,
  83.     u_char            loop,
  84.     const char        *group,
  85.     const char        *interface,
  86.     const char        *mode_str
  87.     )
  88. {
  89.     int            fd ;
  90.     int            st ;
  91.     int            on;
  92.     char            mode = tolower( *mode_str ) ;
  93.     struct in_addr        ifaddr;
  94.     struct in_addr        grpaddr;
  95.     struct ip_mreq        mreq;
  96.  
  97.     grpaddr.s_addr = inet_addr( group ) ;
  98.     if( !IN_MULTICAST( grpaddr.s_addr ) )
  99.     {
  100.         fprintf( stderr, "Invalid multicast group address: %s\n",
  101.             group ) ;
  102.         return( -1 ) ;
  103.     }
  104.  
  105.     if( strlen( mode_str ) != 1 || ( mode != 'r' && mode != 'w' ) )
  106.     {
  107.         fprintf( stderr, "openMulticastSocket: improper mode `%s'\n",
  108.                     mode_str ) ;
  109.         return( -1 ) ;
  110.     }
  111.  
  112.     fd = socket( AF_INET, SOCK_DGRAM, 0 ) ;
  113.     if( fd < 0 )
  114.     {
  115.         perror( "socket" ) ;
  116.         return( fd ) ;
  117.     }
  118.  
  119.     bzero( addr, sizeof( *addr ) ) ;
  120.     addr->sin_family = AF_INET ;
  121.     addr->sin_addr.s_addr = INADDR_ANY ;
  122.     addr->sin_port = htons( port ) ;
  123.  
  124.     ifaddr.s_addr = INADDR_ANY;
  125.  
  126.     if( interface != NULL &&
  127.         ( st = checkInterface( interface, fd, mode, &ifaddr ) ) < 0 )
  128.     {
  129.         close( fd ) ;
  130.         return( st ) ;
  131.     }
  132.  
  133.     switch( mode )
  134.     {
  135.  
  136.         case 'w' :
  137.             if( setsockopt( fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
  138.                             sizeof(ttl) ) )
  139.             {
  140.                 close( fd ) ;
  141.                 perror( "setsockopt TTL" ) ;
  142.                 return( -1 ) ;
  143.             }
  144.  
  145.             if( setsockopt( fd, IPPROTO_IP, IP_MULTICAST_LOOP,
  146.                         &loop, sizeof(loop) ) )
  147.             {
  148.                 close( fd ) ;
  149.                 perror( "setsockopt LOOP" ) ;
  150.                 return( -1 ) ;
  151.             }
  152.  
  153.             addr->sin_addr = grpaddr;
  154.             break ;
  155.  
  156.         case 'r' :
  157.             /* 
  158.              * Allow multiple instances of this program to listen
  159.              * on the same port on the same host. By default only
  160.              * 1 program can bind to the port on a host.
  161.              */
  162.             on = 1;
  163.             if( setsockopt( fd, SOL_SOCKET, SO_REUSEPORT, &on,
  164.                             sizeof(on) ) < 0 )
  165.             {
  166.                 close( fd ) ;
  167.                 perror( "setsockopt REUSEPORT" ) ;
  168.                 return( -1 ) ;
  169.             }
  170.  
  171.             if( bind( fd, addr, sizeof(*addr) ) < 0 )
  172.             {
  173.                 close( fd ) ;
  174.                 perror( "bind" ) ;
  175.                 return( -1 ) ;
  176.             }
  177.  
  178.             mreq.imr_multiaddr = grpaddr;
  179.             mreq.imr_interface = ifaddr;
  180.             if( setsockopt( fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  181.                         &mreq, sizeof(mreq) ) < 0 )
  182.             {
  183.                 close( fd ) ;
  184.                 perror( "setsockopt ADD" ) ;
  185.                 return( -1 ) ;
  186.             }
  187.             break ;
  188.  
  189.     }
  190.  
  191.     return( fd ) ;
  192. }
  193.  
  194.  
  195.  
  196. /*------------------------------------------------------------------------------
  197.  * Make sure the specified interface exists and is capable of doing
  198.  * multicasting.
  199.  *----------------------------------------------------------------------------*/
  200. static int
  201. checkInterface(
  202.     const char    *interface,
  203.     int        fd,
  204.     char        mode,
  205.     struct in_addr    *ifaddr
  206.     )
  207. {
  208.     int        i ;
  209.     struct ifconf    ifc ;
  210.     struct ifreq    *ifr ;
  211.     char        buf[BUFSIZ] ;
  212.  
  213.     ifc.ifc_len = sizeof( buf ) ;
  214.     ifc.ifc_buf = buf ;
  215.     if( ioctl( fd, SIOCGIFCONF, (char *) &ifc ) < 0 )
  216.     {
  217.         perror( "ioctl SIOCGIFCONF" ) ;
  218.         return( -1 ) ;
  219.     }
  220.  
  221.     ifr = ifc.ifc_req;
  222.     for( i = ifc.ifc_len/sizeof(*ifr) ; --i >= 0 ; ifr++ )
  223.     {
  224.         if( ifr->ifr_addr.sa_family != AF_INET )
  225.             continue ;
  226.  
  227.         if( strncmp( ifr->ifr_name, interface, strlen( ifr->ifr_name ) )
  228.             == 0 )
  229.         {
  230.             /* Obtain the interface's assigned network address */
  231.             *ifaddr = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr ;
  232.  
  233.             if( ioctl( fd, SIOCGIFFLAGS, (char *) ifr ) < 0 )
  234.             {
  235.                 perror( "ioctl SIOCGIFFLAGS" ) ;
  236.                 return( -1 ) ;
  237.             }
  238.             if( !( ifr->ifr_flags & IFF_MULTICAST ) )
  239.             {
  240.                 fprintf( stderr, "%s: interface doesn't support"
  241.                     " multicasting\n", interface ) ;
  242.                 return( -1 ) ;
  243.             }
  244.  
  245.             /* Specify the interface to use when sending packets */
  246.             if( mode == 'w' &&
  247.                 setsockopt( fd, IPPROTO_IP, IP_MULTICAST_IF,
  248.                     ifaddr, sizeof(*ifaddr) ) < 0 )
  249.             {
  250.                 perror( "setsockopt MULTICAST" ) ;
  251.                 return( -1 ) ;
  252.             }
  253.             break;
  254.         }
  255.     }
  256.  
  257.     if( ifaddr->s_addr == INADDR_ANY )
  258.     {
  259.         fprintf( stderr, "%s: invalid or unknown interface\n",
  260.             interface ) ;
  261.         return( -1 ) ;
  262.     }
  263.  
  264.     return( 0 ) ;
  265. }
  266.